"""
该文件是一个示例代码，用于测试最简单的排队系统，
并观察和测试影响排队时间的统计分布情况的各因素。
仿真部分的代码只有 50 行，极其简单。

该排队系统包含一个服务台和一个顾客源（泊松分布）
顾客的到达时间符合负指数分布，服务时间的长度符
合泊松分布。
"""

# In[0]:
import simpy
import numpy as np

# In[1]:
LAMBDA = 0.9
MU = 1.5

# In[2]
wait_time_list = []
queue_len_list = []
stay_time_list = []

# In[3]:
def source(env, resource):
    i = 0
    while True:
        yield env.timeout(
            max(
                1,
                np.random.poisson(LAMBDA)
            )
        )
        env.process(customer(env, i))
        queue_len_list.append(
            len(
                resource.queue
            )
        )
        i += 1

# In[4]:
def customer(env, id):
    arrivial_time = env.now
    with counter.request() as req:
        yield req
        wait_time = env.now - arrivial_time
        yield env.timeout(
            max(
                1,
                np.random.exponential(scale=(1/MU))
            )
        )
    stay_time = env.now - arrivial_time
    wait_time_list.append(wait_time)
    stay_time_list.append(stay_time)

# In[5]:
env = simpy.Environment()
counter = simpy.Resource(env, capacity=1)
env.process(
    source(env, counter)
)

# In[6]:
env.run(until=1e4)

# In[7]:
import matplotlib.pyplot as plt
import seaborn as sns

# In[7]:
from scipy.stats import kstest, expon
# 从统计学工具包获得一组 ks 检验的工具，
# 以及负指数分布工具
loc, scale = expon.fit(
    stay_time_list, 
    floc=0)
ks_statistic, p_value = kstest(
    stay_time_list,
    'expon', args=(loc, scale))
alpha = 0.05
print("符合负指数分布：", (p_value < alpha))

# In[8]:
fig, ax = plt.subplots()
sns.histplot(
    stay_time_list,
    # kde=True,
    color='C0', ax=ax)
